package com.denlaku.longan.controller.impl;

import com.denlaku.longan.Const;
import com.denlaku.longan.anno.RequestLimit;
import com.denlaku.longan.controller.LoginController;
import com.denlaku.longan.core.HttpSessionManager;
import com.denlaku.longan.service.UserService;
import com.denlaku.longan.util.BaseUtils;
import com.denlaku.longan.util.JsonUtil;
import com.denlaku.longan.util.RsaUtils;
import com.denlaku.longan.vo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author tianx
 */
@Slf4j
@Controller
public class LoginControllerImpl implements LoginController {
    private static final int MIN_PWD_LENGTH = 8;

    @Autowired
    private UserService userService;

    @RequestLimit(permitsPerSecond = 30)
    @Override
    public void login(HttpServletRequest request, HttpServletResponse response) {
        Map<Object, Object> loginInfo = parseLoginInfo(request);
        String account = BaseUtils.decodeBase64(MapUtils.getString(loginInfo, "account"));
        String decryptPwd = RsaUtils.decrypt(MapUtils.getString(loginInfo, "password"));
        if (StringUtils.isEmpty(account) || StringUtils.length(decryptPwd) < MIN_PWD_LENGTH) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }
        User user = userService.get(account, decryptPwd);
        if (user == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return;
        }
        HttpSession session = request.getSession(true);
        session.setAttribute(Const.KEY_USER_INFO, user);
        HttpSessionManager.putSession(user.getId(), session);
        response.setStatus(HttpStatus.OK.value());
    }

    @SneakyThrows
    private Map<Object, Object> parseLoginInfo(HttpServletRequest request) {
        try (BufferedReader reader = request.getReader()) {
            List<String> lines = new ArrayList<>(2);
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
            return JsonUtil.parseObject(String.join("", lines));
        } catch (Exception e) {
            log.error("Failed to parse login info", e);
        }
        return Collections.emptyMap();
    }
}
